#ifndef __BYTEARRAYS_CPP__
#define __BYTEARRAYS_CPP__

#include "env.h"
#include "bytearrays.h"
#include "msghandle.h"
#include "output.h"
#include "usertype.h"
#include "memorypool.h"

byteArrays blankba;

byteArrays::byteArrays()
{
	cursor = 0;datalen = 0;
	memindex = MemoryPool::instance()->applyMemoryPool();
	if (memindex != -1)
		data = MemoryPool::instance()->m_memoryPool[memindex]->data;
	else
		data = NULL;
}

byteArrays::~byteArrays()
{
	MemoryPool::instance()->releaseMemoryPool(memindex);
}

byteArrays::byteArrays(int t, void* d, int len)
{
	cursor = 0;
	memindex = MemoryPool::instance()->applyMemoryPool();
	data = MemoryPool::instance()->m_memoryPool[memindex]->data;
	memcpy(data, d, len);
	datalen = len;
}

byteArrays::byteArrays(const byteArrays& ba)
{
	memindex = MemoryPool::instance()->applyMemoryPool();
	data = MemoryPool::instance()->m_memoryPool[memindex]->data;
	memcpy(data, ba.data, ba.datalen);
	cursor = ba.cursor;
	datalen = ba.datalen;
}

byteArrays& byteArrays::operator =(const byteArrays& ba)
{
	data = MemoryPool::instance()->m_memoryPool[memindex]->data;
	memcpy(data, ba.data, ba.datalen);
	cursor = ba.cursor;
	datalen = ba.datalen;
	return *this;
}

int byteArrays::readInt()
{
	if (cursor+sizeof(int) > datalen) {
		baExecption.printstack();throw baExecption;
	}
	int retval = *(int*)(data+cursor);
	cursor += sizeof(int);
	return retval;
}

short byteArrays::readShort()
{
	if (cursor+sizeof(short) > datalen) {
		baExecption.printstack();throw baExecption;
	}
	short retval = *(short*)(data+cursor);
	cursor += sizeof(short);
	return retval;
}

char byteArrays::readByte()
{
	if (cursor+sizeof(char) > datalen) {
		baExecption.printstack();throw baExecption;
	}
	char retval = *(char*)(data+cursor);
	cursor += sizeof(char);
	return retval;
}

std::string byteArrays::readString()
{
	int strl = readByte();
	if (strl > MAX_SIZE) {
		baExecption.printstack();throw baExecption;
	}
	if (cursor+strl > datalen) {
		baExecption.printstack();throw baExecption;
	}
	char* c = new char[strl+1];memcpy(c, data+cursor, strl);c[strl] = '\0';cursor += strl;
	std::string retval = c;
	delete[] c;
	return retval;
}

void* byteArrays::readIBytes()
{
	int strl = readInt();cursor -= sizeof(int);
	if (strl > MAX_SIZE) {
		baExecption.printstack();throw baExecption;
	}
	if (cursor+strl > datalen) {
		baExecption.printstack();throw baExecption;
	}
	void* c = (void*)(new char[strl+1]);memcpy(c, data+cursor, strl);cursor += strl;
	return c;
}

byteArrays byteArrays::readByteArrays()
{
	byteArrays ba;
	int strl = readInt();
	if (strl > MAX_SIZE) {
		baExecption.printstack();throw baExecption;
	}
	if (cursor+strl > datalen) {
		baExecption.printstack();throw baExecption;
	}
	memcpy(ba.data, data+cursor, strl);cursor += strl;ba.datalen = strl;
	return ba;
}

int byteArrays::writeInt(int d, int pos)
{
	if (pos != -1) {
		memcpy(data+pos*sizeof(int), &d, sizeof(int));cursor = pos*sizeof(int);
	}
	else {
		memcpy(data+cursor, &d, sizeof(int));cursor += sizeof(int);
	}
	if (cursor > datalen) datalen = cursor;
}
int byteArrays::writeInt(int d)
{
	writeInt(d, -1);
}

int byteArrays::writeShort(short d, int pos)
{
	if (pos != -1) {
		memcpy(data+pos*sizeof(short), &d, sizeof(short));cursor = pos*sizeof(short);
	}
	else {
		memcpy(data+cursor, &d, sizeof(short));cursor += sizeof(short);
	}
	if (cursor > datalen) datalen = cursor;
}
int byteArrays::writeShort(short d)
{
	writeShort(d, -1);
}

int byteArrays::writeByte(char d, int pos)
{
	if (pos != -1) {
		memcpy(data+pos*sizeof(char), &d, sizeof(char));cursor = pos*sizeof(char);
	}
	else {
		memcpy(data+cursor, &d, sizeof(char));cursor += sizeof(char);
	}
	if (cursor > datalen) datalen = cursor;
}
int byteArrays::writeByte(char d)
{
	writeByte(d, -1);
}

int byteArrays::writeString(std::string d, int pos)
{
	if (pos != -1) {
		writeByte(d.length(), pos);pos *= sizeof(int);
		memcpy(data+pos*sizeof(int), d.c_str(), d.length()+1);cursor == pos*sizeof(int) + d.length();
	}
	else {
		writeByte(d.length());
		memcpy(data+cursor, d.c_str(), d.length()+1);cursor += d.length();
	}
	if (cursor > datalen) datalen = cursor;
}
int byteArrays::writeString(std::string d)
{
	writeString(d, -1);
}

int byteArrays::writeIBytes(void* d, int pos)
{
	int l = *(int*)d;
	if (pos != -1) {
		memcpy(data+pos, d, l);cursor = pos+l;
	}
	else {
		memcpy(data+cursor, d, l);cursor += l;
	}
	if (cursor > datalen) datalen = cursor;
}
int byteArrays::writeIBytes(void* d)
{
	writeIBytes(d, -1);
}

int byteArrays::writeByteArrays(byteArrays ba, int pos)
{
	if (pos != -1) {
		writeInt(ba.getlength(), pos);pos *= sizeof(int);
		memcpy(data+pos*sizeof(int), ba.toVoid(), ba.getlength());cursor = pos*sizeof(int)+ba.getlength();
	}
	else {
		writeInt(ba.getlength());
		memcpy(data+cursor, ba.toVoid(), ba.getlength());cursor += ba.getlength();
	}
	if (cursor > datalen) datalen = cursor;
}
int byteArrays::writeByteArrays(byteArrays ba)
{
	writeByteArrays(ba, -1);
}

bool byteArrays::checkByteArrays(int type)
{
}

int byteArrays::getlength()
{
	return datalen;
}

void* byteArrays::toVoid()
{
	return (char*)data;
}

void byteArrays::clear()
{
	cursor = 0;
	memset(data, 0, MEMORYPOOLSIZE);
	datalen = 0;
}

int byteArrays::isEOF()
{
	return (cursor >= datalen);
}

int byteArrays::reset()
{
	cursor = 0;
}

ByteArrayException::ByteArrayException() throw()
{
}

void ByteArrayException::reset(int c, int t, int l, int m) throw()
{
	clientindex = c;type = t;len = l;memindex = m;
}

void ByteArrayException::printstack() throw()
{
	int size = 256;
	void* array[256];
	int stack_num = backtrace(array, size);
	char** stacktrace = backtrace_symbols(array, stack_num);
	for (int i = 0;i < stack_num;i++) {
		wserPrintErr("ByteArrayException.stack:%d:%s\n", i, stacktrace[i]);
	}
	free(stacktrace);
}

void ByteArrayException::printdata() throw()
{
	wserPrintErr("ByteArrayException.(clientindex:%d type:%d len:%d memindex:%d)\n", clientindex, type, len, memindex);
}


class ByteArrayException baExecption;

#endif //__BYTEARRAYS_CPP__
